local lazy_keymaps = {}

local grapple_tag_file = function(scope)
    local grapple = require('grapple')
    if grapple.exists({ scope = scope }) then
        vim.notify('File ' .. vim.fs.basename(vim.fn.bufname()) ..
            ' already marked!', vim.log.levels.INFO)
    else
        grapple.tag({ scope = scope })
    end
end

lazy_keymaps.grapple = {
    { mode = 'n', '<leader>mn',  function() require('grapple').cycle_forward() end },
    { mode = 'n', '<leader>mp',  function() require('grapple').cycle_backward() end },

    { mode = 'n', '<leader>ml',  function() require('grapple').open_tags() end },
    { mode = 'n', '<leader>mm',  grapple_tag_file },
    { mode = 'n', '<leader>1',   function() require('grapple').select({ index = 1 }) end },
    { mode = 'n', '<leader>2',   function() require('grapple').select({ index = 2 }) end },
    { mode = 'n', '<leader>3',   function() require('grapple').select({ index = 3 }) end },
    { mode = 'n', '<leader>4',   function() require('grapple').select({ index = 4 }) end },
    { mode = 'n', '<leader>5',   function() require('grapple').select({ index = 5 }) end },

    { mode = 'n', '<leader>mgl', function() require('grapple').open_tags({ scope = 'global' }) end },
    { mode = 'n', '<leader>mgm', function() grapple_tag_file('global') end },
    { mode = 'n', '<leader>g1',  function() require('grapple').select({ scope = 'global', index = 1 }) end },
    { mode = 'n', '<leader>g2',  function() require('grapple').select({ scope = 'global', index = 2 }) end },
    { mode = 'n', '<leader>g3',  function() require('grapple').select({ scope = 'global', index = 3 }) end },
    { mode = 'n', '<leader>g4',  function() require('grapple').select({ scope = 'global', index = 4 }) end },
    { mode = 'n', '<leader>g5',  function() require('grapple').select({ scope = 'global', index = 5 }) end },
}

lazy_keymaps.surround = {
    -- check `surround_km_name` in surround.lua for actions
    -- of these keymaps

    { mode = 'i', '<c-g>p' },
    { mode = 'i', '<c-g>P' },

    -- normal mode, enter operator pending mode then
    -- specity the pair type
    { mode = 'n', 'yp' },
    { mode = 'n', 'yP' },
    -- normal mode, just specify the pair type
    { mode = 'n', 'ypp' },
    { mode = 'n', 'yPP' },
    { mode = 'n', 'dp' },
    { mode = 'n', 'cp' },
    { mode = 'n', 'cP' },

    -- visual mode
    { mode = 'v', 'P' },
    { mode = 'v', 'gP' },
}
lazy_keymaps.easy_align = {
    {
        mode = { 'n', 'x' },
        'ga',
        '<Plug>(EasyAlign)'
    }
}
lazy_keymaps.leap = {
    {
        mode = { 'n', 'x', 'o' },
        '<leader>s',
        function()
            require('leap').leap {
                target_windows = require('lin.utils').cur_tab_focusable_wins()
            }
        end
    }
}
lazy_keymaps.hop = {
    {
        mode = { 'n', 'x', 'o' },
        'ss',
        '<cmd>HopLineStart<cr>',
    }
}
lazy_keymaps.flash = {
    {
        mode = { 'n', 'x', 'o' },
        'sf',
        function()
            require('flash').jump {
                jump = {
                    pos = 'start',
                }
            }
        end
    },
    {
        mode = { 'n', 'x', 'o' },
        'sl',
        function()
            require('flash').jump {
                jump = {
                    pos = 'end',
                }
            }
        end
    },
    {
        mode = { 'n', 'x', 'o' },
        'sb',
        function()
            require('flash').jump {
                jump = {
                    pos = 'start',
                    offset = -1
                }
            }
        end
    },
    {
        mode = { 'n', 'x', 'o' },
        'sa',
        function()
            require('flash').jump {
                jump = {
                    pos = 'end',
                    offset = 1
                }
            }
        end
    },
    {
        mode = { 'n', 'x', 'o' },
        'se',
        function()
            require('flash').jump {
                search = { mode = 'search', max_length = 0 },
                pattern = '$',
                jump = {
                    pos = 'end',
                },
                -- label = {
                --     before = { 0, 0 },
                --     after = false,
                -- },
            }
        end
    },
}
vim.keymap.del('n', 'gcc');
vim.keymap.del('o', 'gc');
lazy_keymaps.comment = {
    { mode = { 'n', 'x' }, 'gc' },
    { mode = { 'n', 'x' }, 'gb' },
}
lazy_keymaps.telescope = {
    {
        mode = 'n',
        '<leader>la',
        function()
            require('telescope.builtin').find_files(
                { hidden = true, no_ignore = true }
            )
        end
    },
    {
        mode = 'n',
        '<leader>ll',
        function() require('telescope.builtin').find_files() end
    },
    {
        mode = 'n',
        '<leader>lo',
        function() require('telescope.builtin').oldfiles() end
    },
    {
        mode = 'n',
        '<leader>lg',
        function() require('telescope.builtin').live_grep() end
    },
    {
        mode = 'n',
        '<leader>lb',
        function() require('telescope.builtin').buffers() end
    },
    {
        mode = 'n',
        '<leader>ld',
        function() require('telescope.builtin').diagnostics() end
    },
    {
        mode = 'n',
        '<leader>lm',
        function() require('telescope.builtin').marks() end
    },
    {
        mode = 'n',
        '<leader>lr',
        function() require('telescope.builtin').registers() end
    },
    {
        mode = 'n',
        '<leader>lwl',
        function() require('telescope.builtin').lsp_document_symbols() end
    },
    {
        mode = 'n',
        '<leader>lww',
        function() require('telescope.builtin').lsp_dynamic_workspace_symbols() end
    },
    {
        mode = 'n',
        '<leader>lh',
        function() require('telescope.builtin').help_tags() end
    },
    {
        mode = 'n',
        '<leader>ls',
        function() require('telescope').extensions.possession.list() end
    },
}
lazy_keymaps.nvim_tree = {
    {
        mode = 'n',
        '<leader>tt',
        function() require('nvim-tree.api').tree.toggle() end
    },
    {
        mode = 'n',
        '<leader>tc',
        function()
            local nvim_tree = require('nvim-tree.api').tree
            local cur_file_dir = vim.fn.expand('%:p:h')
            if nvim_tree.is_tree_buf() then return end
            if nvim_tree.is_visible() then
                nvim_tree.change_root(cur_file_dir)
                nvim_tree.find_file({ focus = true })
            else
                nvim_tree.open({ path = cur_file_dir, find_file = true })
            end
        end
    },
}

local init_keymaps = {}

init_keymaps.undotree = {
    {
        mode = 'n',
        '<leader>u',
        '<cmd>UndotreeToggle<cr>',
    },
}

init_keymaps.gitsigns = {
    {
        mode = 'n',
        '<leader>ghp',
        '<cmd>Gitsigns prev_hunk<cr>',
    },
    {
        mode = 'n',
        '<leader>ghn',
        '<cmd>Gitsigns next_hunk<cr>',
    },
    {
        mode = { 'n', 'x' },
        '<leader>ghr',
        ':Gitsigns reset_hunk<cr>',
    },
    {
        mode = { 'n', 'x' },
        '<leader>ghs',
        ':Gitsigns stage_hunk<cr>',
    },
    {
        mode = 'n',
        '<leader>ghu',
        '<cmd>Gitsigns undo_stage_hunk<cr>',
    },
}

return {
    lazy = lazy_keymaps,
    init = init_keymaps,
    setup_init_keymaps = function()
        for _, keymaps in pairs(init_keymaps) do
            for _, keymap in ipairs(keymaps) do
                vim.keymap.set(keymap.mode, keymap[1], keymap[2], keymap.opts)
            end
        end
    end,
}
